package fudan.se.project.domain.conference;

import com.fasterxml.jackson.annotation.JsonIgnore;
import fudan.se.project.domain.conference.production.Paper;
import fudan.se.project.domain.conference.role.Author;
import fudan.se.project.domain.conference.role.Chair;
import fudan.se.project.domain.conference.role.PcMember;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;
import java.util.Date;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

import static fudan.se.project.domain.conference.Conference.ConferenceStage.PREPARING;
import static fudan.se.project.domain.conference.Conference.ConferenceState.APPLYING;

@Entity
@Setter
@Getter
@NoArgsConstructor
public class Conference {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String shortname;
    private String fullname;


    private String place;

    private Date dateStart;

    private Date deadline;

    private Date dateRelease;
    private Date dateEnd;

    @Enumerated(EnumType.STRING)
    private ConferenceState state;

    @Enumerated(EnumType.STRING)
    private ConferenceStage stage;

    @Enumerated(EnumType.STRING)
    private AllocationStrategy strategy;

    @JsonIgnore
    @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL}, mappedBy = "conference")
    private Set<Topic> topics = new HashSet<>();

    @JsonIgnore
    @OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.ALL}, mappedBy = "conference")
    private Chair chair;

    @JsonIgnore
    @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL}, mappedBy = "conference")
    private Set<PcMember> pcMembers = new HashSet<>();

    @JsonIgnore
    @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL}, mappedBy = "conference")
    private Set<Author> authors = new HashSet<>();


    @JsonIgnore
    @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL}, mappedBy = "conference")
    private Set<Paper> papers = new HashSet<>();


    public Conference(

            String shortname,
            String fullname,

            String place,

            Date dateStart,

            Date deadline,

            Date dateRelease,
            Date dateEnd
    ) {

        this.shortname = shortname;
        this.fullname = fullname;
        this.place = place;
        this.dateStart = dateStart;
        this.deadline = deadline;
        this.dateRelease = dateRelease;
        this.dateEnd = dateEnd;


        this.state = APPLYING;
        this.stage = PREPARING;
    }


    public enum ConferenceState {
        APPLYING,   // 0
        REJECTED,   // 1
        PASSED,     // 2

    }

    public enum ConferenceStage {
        PREPARING,          // 0
        CONTRIBUTION_START, // 1
        CONTRIBUTION_END,   // 2
        REVIEW_START,       // 3
        REVIEW_END,         // 4
        RESULT_RELEASE,     // 5
        FINAL_RELEASE,      // 6
        CONFERENCE_START,   // 7
        CONFERENCE_END      // 8
    }

    public enum AllocationStrategy {
        BY_TOPIC,   // 0
        BALANCED    // 1
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Conference)) return false;
        Conference that = (Conference) o;
        return getId().equals(that.getId());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getId());
    }
}
